<template>
	<xn-form-container title="上传图片" :width="700" v-model:open="open" :destroy-on-close="true" @close="onClose">
		<div class="flex justify-between items-center mb-2">
			<a-space>
				<a-typography-text strong underline class="w-52 line-clamp-1">{{ group.name }}</a-typography-text>
				<a-typography-text strong>当前：{{ fileList.length }}张</a-typography-text>
				<a-typography-text strong>成功：{{ fileSuccessList.length }}张</a-typography-text>
			</a-space>

			<a-space>
				<a-alert :message="`最多一次性上传${maxCount}张图片`" type="warning" />
				<a-button @click="uploadHandler" :disabled="fileList.length === 0">上传图片</a-button>
			</a-space>
		</div>
		<a-spin :spinning="imgUploading" :tip="imgUploadingTip">
			<div class="h-[70vh] overflow-hidden overflow-y-auto custom-scrollbar">
				<a-upload
					:max-count="maxCount"
					accept="image/*"
					multiple
					v-model:file-list="fileList"
					:before-upload="beforeUpload"
					list-type="picture-card"
					@preview="handlePreview"
				>
					<div v-if="fileList.length < maxCount">
						<plus-outlined />
						<div style="margin-top: 8px">选择图片</div>
					</div>
				</a-upload>
			</div>
		</a-spin>

		<a-image
			:alt="previewTitle"
			:width="200"
			:style="{ display: 'none' }"
			:preview="{
				visible: previewVisible,
				onVisibleChange: handleCancel
			}"
			:src="previewImage"
		/>

		<template #footer>
			<a-button type="primary" @click="onSubmit" :disabled="fileSuccessList.length === 0" :loading="submitLoading"
				>保存图片
			</a-button>
		</template>
	</xn-form-container>
</template>

<script setup name="eduCourseCateForm">
	import { nanoid } from 'nanoid'
	import { ref } from 'vue'
	import fileApi from '@/api/dev/fileApi'
	import { message } from 'ant-design-vue'
	import dayjs from 'dayjs'
	import eduImgApi from '@/api/biz/eduImgApi'

	const maxCount = 50
	const imgUploading = ref(false)
	const imgUploadingTip = ref('')

	function getBase64(file) {
		return new Promise((resolve, reject) => {
			const reader = new FileReader()
			reader.readAsDataURL(file)
			reader.onload = () => resolve(reader.result)
			reader.onerror = (error) => reject(error)
		})
	}

	const previewVisible = ref(false)
	const previewImage = ref('')
	const previewTitle = ref('')
	const fileList = ref([])
	const fileSuccessList = computed(() => fileList.value.filter((file) => file.status === 'done'))
	const handleCancel = () => {
		previewVisible.value = false
		previewTitle.value = ''
	}
	const handlePreview = async (file) => {
		if (!file.preview) {
			file.preview = await getBase64(file.originFileObj)
		}
		previewImage.value = file.url || file.preview
		previewVisible.value = true
		previewTitle.value = file.name || file.url.substring(file.url.lastIndexOf('/') + 1)
	}

	const beforeUpload = (file) => {
		fileList.value = [...(fileList.value || []), file]
		return false
	}
	// 抽屉状态
	const open = ref(false)
	const emit = defineEmits({ successful: null })

	// 表单数据
	const submitLoading = ref(false)
	const group = ref({})

	// 打开抽屉
	const onOpen = (record) => {
		console.log(record)
		group.value = record
		open.value = true
	}
	// 关闭抽屉
	const onClose = () => {
		fileList.value = []
		open.value = false
	}
	const uploadHandler = () => {
		console.log('uploadHandler', fileList.value)
		imgUploading.value = true
		imgUploadingTip.value = '正在获取上传凭证...'
		fileApi
			.getOssStsInfo()
			.then((res) => {
				if (!res) {
					message.error('获取签名失败')
					return {}
				}
				imgUploadingTip.value = '图片上传中...'
				return res
			})
			.then((data) => {
				const multiUploadFile = fileList.value.map((file) => {
					let formData = new FormData()
					formData.append('success_action_status', '200')
					formData.append('policy', data.policy)
					formData.append('x-oss-signature', data.signature)
					formData.append('x-oss-signature-version', 'OSS4-HMAC-SHA256')
					formData.append('x-oss-credential', data.x_oss_credential)
					formData.append('x-oss-date', data.x_oss_date)
					const key = `${data.dir}/${dayjs().format('YYYY/MM/DD')}/${nanoid()}.` + file.name.split('.').pop()
					formData.append('key', key) // 文件名

					formData.append('x-oss-security-token', data.security_token)
					formData.append('file', file.originFileObj) // file 必须为最后一个表单域

					return fetch(data.host, {
						method: 'POST',
						body: formData
					})
						.then((response) => {
							if (response.ok) {
								return {
									...file,
									uid: nanoid(),
									status: 'done',
									url: `${data.host + '/' + key}`
								}
							} else {
								return {
									...file,
									uid: nanoid(),
									status: 'error'
								}
							}
						})
						.catch((error) => {
							console.error('发生错误:', error)
							return {
								...file,
								uid: nanoid(),
								status: 'error'
							}
						})
				})

				return Promise.all(multiUploadFile)
			})
			.then((list) => {
				fileList.value = list
				message.success('图片上传完成')
			})
			.catch((error) => {
				console.error('发生错误:', error)
				message.error('未知错误', error)
			})
			.finally(() => {
				imgUploading.value = false
				imgUploadingTip.value = ''
			})
	}

	// 验证并提交数据
	const onSubmit = async () => {
		const saveImgs = fileSuccessList.value.map((file) => ({
			sortCode: 99,
			name: file.name,
			url: file.url,
			size: file.size,
			imgGroupPath: [...group.value.parentPath, group.value.id]
		}))
		submitLoading.value = true
		eduImgApi
			.eduImgSubmitForm(saveImgs, false)
			.then(() => {
				onClose()
				emit('successful')
			})
			.finally(() => {
				submitLoading.value = false
			})
	}

	// 抛出函数
	defineExpose({
		onOpen
	})
</script>
<style scoped lang="less">
	/* you can make up upload button and sample style by using stylesheets */
	.ant-upload-select-picture-card i {
		font-size: 32px;
		color: #999;
	}

	.ant-upload-select-picture-card .ant-upload-text {
		margin-top: 8px;
		color: #666;
	}
</style>
